/*
 * Agenda Médica do Dia
 *  
 */
package sao.modelo;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.sql.Time;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import sao.dao.Dao;

public class AgendaDiaria {
	
	private List<HorarioAgendamento> agenda;
	private List<Time> agendamentos;
	private Disponibilidade disp;
	private int DURACAO_AGENDAMENTO;
	private int ano, mes, dia;
	
	
	/**
	 * Construtor parametrizado, inicia a List de HorarioAgendamento
	 * @param ano - Ano da agenda
	 * @param mes - Mês da agenda, janeiro = 1
	 * @param dia - Data (dia) da agenda
	 * @param medico - Usuário médico cuja agenda deseja-se exibir
	 * @throws SQLException
	 * @throws ClassNotFoundException 
	 * @throws UnsupportedEncodingException 
	 */
	public AgendaDiaria(int ano, int mes, int dia, UsuarioMedico medico, int duracaoConsulta)
			throws ClassNotFoundException, SQLException, UnsupportedEncodingException{
		this.DURACAO_AGENDAMENTO = duracaoConsulta;
		this.agenda = new ArrayList<HorarioAgendamento>();

		Calendar cal = new GregorianCalendar(ano, mes-1, dia);// Ajusta o mês
		int diaDaSemana = cal.get(Calendar.DAY_OF_WEEK);// Considerando domingo = 1
		
		Dao dao = new Dao();
		// Consulta banco: pega a disponibilidade do médico para este dia
		disp = dao.getDisponibilidade(medico, diaDaSemana);
		// Consulta os agendamentos já existentes no dia
		agendamentos = dao.getAgendamentosDia(medico, ano, mes, dia);// O mês considera janeiro = 1, devido ao fato
																	 // que é assim que o SQL o considera
		this.ano = ano;
		this.mes = mes - 1;
		this.dia = dia;
		
		setAgenda();
	}//FIM Construtor

	
	/**
	 * Retorna a agenda: uma List de HorarioAgendamento
	 * @return A List agenda
	 */
	public List<HorarioAgendamento> getAgenda() {
		return agenda;
	}

	
	/**
	 * Retorna o tamanho da agenda, ou seja, a quantidade de horários disponíveis no dia
	 * @return Um inteiro representando o tamanho da agenda
	 */
	public int size(){
		return this.agenda.size();
	}
	

	/**
	 * Constrói a agenda, alimentando todos os horários nos quais o médico
	 * estará disponível 
	 * @throws UnsupportedEncodingException 
	 */
	private void setAgenda() throws UnsupportedEncodingException {
		// Constrói a agenda do dia
		DateFormat fTime = DateFormat.getTimeInstance(DateFormat.SHORT);
		
		// Declara variáveis auxiliares
		Calendar proximoHorario; // Cursor para o horário
		HorarioAgendamento horario; // Cada horário de atendimento
		String hora; // A hora do Horario
		String status; // O status de cada horário
		
		// Testa se há horário disponível, se não houver, encerra o método
		if(disp == null)
			return;
		
		// Verifica se existe disponibilidade para o primeiro período
		if (disp.existePrimeiroPeriodo()) {
			// Define algumas variáveis auxiliares
			Calendar inicioPrimeiroHorario = Calendar.getInstance();
			inicioPrimeiroHorario.setTime(disp.getInicioHorario1());
			
			Calendar fimPrimeiroHorario = Calendar.getInstance();
			fimPrimeiroHorario.setTime(disp.getFimHorario1());
			
			proximoHorario = inicioPrimeiroHorario; // Cursor para o horário
			// Testa se o próximo horário ainda é ANTES do fim do primeiro horário
			boolean existeProximoHorario = proximoHorario.before(fimPrimeiroHorario);
			
			// Inicia loop para adicionar os horários à agenda do dia
			while(existeProximoHorario){
				hora = fTime.format(proximoHorario.getTime());
				status = this.getStatus(proximoHorario.getTime());
				horario = new HorarioAgendamento(hora, status);
				this.agenda.add(horario);
				
				// Incrementa o cursor
				proximoHorario.add(Calendar.MINUTE, DURACAO_AGENDAMENTO);
				
				// Atualiza o teste
				existeProximoHorario = proximoHorario.before(fimPrimeiroHorario);
			}
		}
		
		// Verifica se existe disponibilidade para o segundo período
		if (disp.existeSegundoPeriodo()) {
			// Define algumas variáveis auxiliares
			Calendar inicioSegundoHorario = Calendar.getInstance();
			inicioSegundoHorario.setTime(disp.getInicioHorario2());
			
			Calendar fimSegundoHorario = Calendar.getInstance();
			fimSegundoHorario.setTime(disp.getFimHorario2());
			
			proximoHorario = inicioSegundoHorario; // Cursor para o horário
			
			// Testa se o próximo horário ainda é ANTES do fim do primeiro horário
			boolean existeProximoHorario = proximoHorario.before(fimSegundoHorario);
			
			// Inicia loop para adicionar os horários à agenda do dia
			while(existeProximoHorario){
				hora = fTime.format(proximoHorario.getTime());
				status = this.getStatus(proximoHorario.getTime());
				horario = new HorarioAgendamento(hora, status);
				this.agenda.add(horario);
				
				// Incrementa o cursor
				proximoHorario.add(Calendar.MINUTE, DURACAO_AGENDAMENTO);	

				// Atualiza o teste
				existeProximoHorario = proximoHorario.before(fimSegundoHorario);
			}//FIM while
		}//FIM if
	}


	private String getStatus(Date data) throws UnsupportedEncodingException {
		DateFormat df = DateFormat.getTimeInstance();
		String statusHorario;
		String hora = df.format(data);
		if (agendamentos.contains(data)) {
			statusHorario = "OCUPADO";
		} else {
			String diaHoraCod = URLEncoder.encode(ano + "-" + (mes+1) + "-" + dia + " " + hora, "UTF-8");
			statusHorario = "LIVRE - <a href='efetuarAgendamento?horario=" + diaHoraCod + "'>Agendar</a>";
		}
		return statusHorario;
	}

	
}//FIM Classe AgendaDiaria
